import axios from 'axios'
import { ls } from '@/utils/storage.js'

const createRequest = (axiosConfig, extraConfig = {}) => {
  const { noMsg } = extraConfig

  // 创建 axios 实例
  const serve = axios.create({
    baseURL: import.meta.env.VITE_BASE_URL,               // 基础服务地址
    timeout: 10000,                                       // 超时时间 单位毫秒
    headers: {                                            // 请求头设置
      'Content-Type': 'application/json;charset=utf-8'
    },
  })

  // 请求拦截
  // config: {
  //   adapter: {},
  //   baseURL: '',
  //   url: '',
  //   data: '',
  //   env: {},
  //   headers: {},
  //   method: '',
  //   timeout: 5000,
  // }
  serve.interceptors.request.use(
    config => {
      const token = ls.get(ls.token)
      token && (config.headers.Authorization = token)
      return config
    }
  )

  // 响应拦截
  // response: {
  //   config: {},
  //   data: {
  //     code: 0,
  //     data: {},
  //     msg: "",
  //   },
  //   headers: {},
  //   request: {},
  //   status: 200,
  //   statusText: "OK"
  // }
  serve.interceptors.response.use(
    response => {
      const { data, status } = response
      const { code, msg } = data || {}
      if (code != 0 && msg && !noMsg) ElMessage.error(msg)        // 全局提示错误信息
      if (status != 200) return Promise.reject(response)          // http 状态码 status != 200  catch 中返回错误信息
      if (code == 302) location.href = `#${data.location}`        // 自定义状态码 code == 302    token 已过期，重定向到登录页面
      return data                                                 // 自定义状态码 code 为其他值   then 中返回数据
    },
    error => {
      return Promise.reject(error)
    }
  )

  const { data, ...options } = axiosConfig
  const method = options?.method.toUpperCase()
  const prmsList = ['GET', 'DELETE']
  prmsList.includes(method) ? options.params = data : options.data = data  // get delete 请求参数放在 params 中，其它请求参数放在 data 中
  return serve(options)
}

/**
 * 请求封装
 * @param {Object} axiosConfig axios 请求配置 https://www.axios-http.cn/docs/req_config
 * @param {Object} extraConfig 额外配置
 * @param {Boolean} extraConfig.noMsg 是否不全局提示错误信息
 * @param {Boolean} extraConfig.isDelete 是否为删除操作，删除操作需要二次确认
 * @returns {Promise}
 */
const request = (axiosConfig, extraConfig = {}) => {
  return new Promise((resolve) => {
    const { isDelete, title, message } = extraConfig
    if (isDelete) {
      ElMessageBox.confirm(message || '删除后将无法恢复', title || '确认删除？', { cancelButtonText: '取消', confirmButtonText: '确认' })
        .then(() => resolve(createRequest(axiosConfig, extraConfig)))
        .catch(() => resolve({ tip: 'cancel' }))
    } else {
      resolve(createRequest(axiosConfig, extraConfig))
    }
  })
}

export default request